package com.okhttp.retrofit;

import com.okhttp.interceptor.HeaderInterceptor;
import com.okhttp.utils.RetrofitLog;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import okhttp3.logging.HttpLoggingInterceptor.Level;
import okhttp3.logging.HttpLoggingInterceptor.Logger;
import retrofit2.Converter;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * @author GYL
 * @dateTime 2020/4/21-14:13
 * @description Retrofit client
 */
public class RetrofitClient {
  
  private static volatile RetrofitClient instance;
  private Retrofit retrofit;
  private Object retrofitService;
  private Config mConfig;
  private boolean isDebug;
  
  public synchronized static RetrofitClient getInstance() {
    if (instance == null) {
      synchronized (RetrofitClient.class) {
        if (instance == null) {
          instance = new RetrofitClient();
        }
      }
    }
    return instance;
  }
  
  private RetrofitClient() { }
  
  public boolean isDebug(){
    return this.isDebug;
  }
  
  public void setRetrofitConfig(Config config){
    this.mConfig=config;
    this.isDebug=config.isDebug;
  }
  
  public void createRetrofit(){
    Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
    //定义网络请求域名
    retrofitBuilder.baseUrl(mConfig.hostUrl);
    //先添自定的converter
    boolean isHasGsonConverterFactory=false;
    if (mConfig.converterFactoryList != null) {
      for (Converter.Factory factory : mConfig.converterFactoryList) {
        retrofitBuilder.addConverterFactory(factory);
        if(factory instanceof GsonConverterFactory){
          //已经包含GSONConverterFactory
          isHasGsonConverterFactory=true;
        }
      }
    }
    if(!isHasGsonConverterFactory){
      //不包含GSONConverterFactory
      retrofitBuilder.addConverterFactory(GsonConverterFactory.create());
    }
    //
    retrofitBuilder.client(createOkHttpClient());
    retrofit = retrofitBuilder.build();
  }

  public Retrofit getRetrofit(){
    return retrofit;
  }
  
  private OkHttpClient createOkHttpClient(){
    //调试模式下打印日志
    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new Logger() {
      @Override
      public void log(String message) {
        RetrofitLog.d("RetrofitClient", message);
      }
    });
    loggingInterceptor.setLevel(mConfig.isDebug ? Level.BODY : Level.NONE);
    //OKhttp client
    OkHttpClient.Builder okBuilder = new OkHttpClient.Builder();
    //添加Header,HeaderInterceptor 不库为空时，HeaderMap无效
    if(mConfig.mHeaderInterceptor!=null){
      okBuilder.addInterceptor(mConfig.mHeaderInterceptor);
    }else{
      if(mConfig.headers!=null){
        okBuilder.addInterceptor(new HeaderInterceptor(mConfig.headers));
      }
    }
    //默认使用CacheInterceptor
    if(mConfig.mCacheInterceptor!=null){
      okBuilder.addInterceptor(mConfig.mCacheInterceptor);
    }
    //
    if (mConfig.interceptorList != null && mConfig.interceptorList.size() > 0) {
      for (Interceptor interceptor : mConfig.interceptorList) {
        okBuilder.addInterceptor(interceptor);
      }
    }
    okBuilder.addInterceptor(loggingInterceptor);
    //失败重连
    okBuilder.retryOnConnectionFailure(true)
      //超时时间
      .connectTimeout(30, TimeUnit.SECONDS)
      .writeTimeout(10, TimeUnit.SECONDS)
      .readTimeout(10, TimeUnit.SECONDS);
    OkHttpClient client=okBuilder.build();
    return client;
  }
  
  /**
   * 创建Retrofit 服务接口
   * @param service
   * @param <T>
   * @return
   */
  public <T> T createService(Class<T> service) {
    if(retrofit==null){
      createRetrofit();
    }
    //相同的Service 不需要重建
    if(retrofitService!=null && service.isAssignableFrom(retrofitService.getClass())){
      return (T) retrofitService;
    }
    retrofitService=retrofit.create(service);
    return (T) retrofitService;
  }
  
   public static class Config{
  
     /**
      * 服务器URL,必须以“/”结尾
      */
    private String hostUrl;
     /**
      * 是否打打包输出
      */
     private boolean isDebug;
     /**
      * 数据转换器：GSON，String
      */
     private List<Converter.Factory> converterFactoryList;
  
     /**
      * 拦截器列表
      */
     private List<Interceptor> interceptorList;
     /**
      *  缓存拦截器
      */
     private Interceptor mCacheInterceptor;
  
     /**
      * 请求Header 拦截器，不为空时， Map Header无效
      * */
     private Interceptor mHeaderInterceptor;
     
     /**
      * Header 实现方法
      */
     private Map<String,String> headers;
    
     public Config(){}
     
     public Config withHostUrl(String url){
       this.hostUrl=url;
       return this;
     }
  
     public Config withDebug(boolean isDebug){
       this.isDebug=isDebug;
       return this;
     }
  
     /**
      * 添加数据解析器，按添加顺序解析
      * @param factory
      */
     public Config addConverterFactory(Converter.Factory factory){
       if(converterFactoryList ==null){
         converterFactoryList =new ArrayList<>();
       }
       converterFactoryList.add(factory);
       return this;
     }
  
     public Config witlisthConverterFactories(List<Converter.Factory> converterFactories){
       if(converterFactoryList!=null){
         this.converterFactoryList.addAll(converterFactories);
       }else{
         this.converterFactoryList=converterFactories;
       }
       return this;
     }
  
     public Config withInterceptorList(List<Interceptor> interceptorList){
       if(this.interceptorList!=null){
         this.interceptorList.addAll(interceptorList);
       }else{
         this.interceptorList=interceptorList;
       }
       return this;
     }
  
     public Config addInterceptor(Interceptor interceptor){
       if(interceptorList ==null){
         interceptorList =new ArrayList<>();
       }
       interceptorList.add(interceptor);
       return this;
     }
  
     public Config withCacheInterceptor(Interceptor cacheInterceptor){
       this.mCacheInterceptor=cacheInterceptor;
       return this;
     }
  
     public Config withHeaderInterceptor(Interceptor headerInterceptor){
       this.mHeaderInterceptor=headerInterceptor;
       return this;
     }
     
     public Config withHeaders(Map<String,String> headers){
       if(headers!=null){
         this.headers.putAll(headers);
       }else {
         this.headers=headers;
       }
       return this;
     }
  
     public Config addHeader(String key, String value){
       if(headers==null){
         headers=new HashMap<>();
       }
       headers.put(key,value);
       return this;
     }
     
     
     
  }
  
  
}